package de.justphil.tcg.tcgserver.game.mechanics.property.properties;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.List;

import de.justphil.tcg.tcgserver.commons.exceptions.TCGException;
import de.justphil.tcg.tcgserver.game.mechanics.event.Event;
import de.justphil.tcg.tcgserver.game.mechanics.game.Attack;
import de.justphil.tcg.tcgserver.game.mechanics.game.Game;
import de.justphil.tcg.tcgserver.game.mechanics.monster.Monster;
import de.justphil.tcg.tcgserver.game.mechanics.monster.MonsterList;
import de.justphil.tcg.tcgserver.game.mechanics.property.Property;

public class Retaliation extends Property {

	public Retaliation(Game game) {

		super(game);
	}
	
	private boolean retaliation = true;

	@Override
	public int getType() {

		return PROPERTY_RETALIATION;
	}

	@Override
	protected MonsterList handleEvent(Event event) {

		int eventType = event.getType();

		switch (eventType) {
		case Event.EVENT_ATTACK_FINISHED:

			handleAttack((Attack) event.getData());
			break;

		case Event.EVENT_MONSTER_DIED:

			handleMonsterDied((Monster) event.getData());
			break;

		default:
			assert false;
			break;
		}
		return null;
	}

	@Override
	protected List<Integer> getListeningEventTypes() {
	
		List<Integer> types = super.getListeningEventTypes();
		types.add(Event.EVENT_ATTACK_FINISHED);
		types.add(Event.EVENT_MONSTER_DIED);
	
		return types;
	}

	private void handleMonsterDied(Monster monster) {

		if (getMonster().equals(monster)) {

			retaliation = false;
		}
	}

	private void handleAttack(Attack attack) {

		Monster monster = getMonster();

		if (monster.getProperties(PROPERTY_SLEEPING).size() > 0) {

			return;
		}

		if (retaliation) {

			if (attack.getTarget().equals(monster)) {

				Attack counterAttack = new Attack(attack.getTarget(),
						attack.getAttacker());
				try {

					getScheduler()
							.scheduleFirst(
									new Event(Event.EVENT_ATTACK_INVOKED,
											counterAttack), 0.0);

					getScheduler().scheduleLast(
							new Event(Event.EVENT_ATTACK, counterAttack), 0.0);

					getScheduler().scheduleLast(
							new Event(Event.EVENT_ATTACK_FINISHED,
									counterAttack), 0.0);

				} catch (TCGException e) {

					assert false: e.getMessage();
				}
			}

		} else {

			/*
			 * If the monster will be resurrected retaliation is enabled again.
			 */
			retaliation = true;
		}
	}
	
	@Override
	public void writeData(Game game, DataOutput out) throws IOException {

		super.writeData(game, out);
		
		out.writeBoolean(retaliation);
	}
	
	@Override
	public void readData(Game game, DataInput in) throws IOException {

		super.readData(game, in);

		retaliation = in.readBoolean();
	}
}
